package com.weaver.qfengx.action;

import com.google.common.collect.Lists;
import com.weaver.qfengx.*;
import com.weaver.qfengx.annotation.ActionParamCheck;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.*;
import weaver.workflow.request.RequestManager;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public abstract class BaseAction implements Action {

    protected LogUtils log = new LogUtils(this.getClass());

    private String actionName = "封装后的流程节点Action基础类";

    public void setActionName(String name) {
        this.actionName = name;
    }

    protected void setLog(Class clazz) {
        this.log = new LogUtils(clazz);
    }

    protected String workflowid = "";
    protected String requestid = "";
    protected String creatorname = "";
    protected String creatorid = "";
    protected String formid = "";
    protected String maintable = "";
    protected String requestname = "";
    protected Map<String, String> mainTableMap = MapUtils.newCaseInsensitiveMap();

    protected boolean isOk = true;
    protected String message = "";
    protected RequestInfo requestInfo;

    public abstract void execCode(RequestInfo requestInfo) throws Exception;

    @Override
    public String execute(RequestInfo requestInfo) {
        this.requestInfo = requestInfo;
        try {
            // 要做初始化，因为系统bean使用的是单例模式
            isOk = true;
            message = "";
            log.writeLog("=========开始执行:" + actionName +" Action==============> " + DateUtils.datetime());
            workflowid = requestInfo.getWorkflowid();
            requestid = requestInfo.getRequestid();
            creatorname = requestInfo.getCreatorid();
            RequestManager requestManager = requestInfo.getRequestManager();
            creatorid = StringUtils.val(requestManager.getCreater());
            formid = StringUtils.val(requestManager.getFormid());
            maintable = "formtable_main_" + -requestManager.getFormid();
            requestname = requestManager.getRequestname();
            log.writeLog("=======> 流程基本信息 <======");
            log.writeLog("requestname => " + requestname + ", workflowid => " + workflowid + ", creatorid => " + creatorid + ", creatorname => " + creatorname);
            log.writeLog("requestid => " + requestid + ", formid => " + formid + ", maintable => " + maintable);
            // 主表信息
            MainTableInfo mainTableInfo = requestInfo.getMainTableInfo();
            for (Property property : mainTableInfo.getProperty()) {
                log.writeLog("propertyname => " + property.getName() + ", propertyvalue => " + property.getValue());
                mainTableMap.put(property.getName(), property.getValue());
            }

            long startExecCode = System.currentTimeMillis();
            log.writeLog("开始执行参数检查 => " + DateUtils.datetime());
            boolean checkRes = checkParamAnno(this);
            log.writeLog("参数检查结果 => " + checkRes);
            if (checkRes) {
                log.writeLog("开始执行业务逻辑代码 => " + DateUtils.datetime());
                // 业务逻辑代码开始
                execCode(requestInfo);
                // 业务逻辑代码结束
                log.writeLog("结束执行业务逻辑代码 => cost: " + (System.currentTimeMillis() - startExecCode) + ", " + DateUtils.datetime());
            }

            log.writeLog("=========执行结束" + actionName + " Action==============> " + DateUtils.datetime());

            if (isOk) {
                return Action.SUCCESS;
            } else {
                requestInfo.getRequestManager().setMessagecontent(message);
                requestInfo.getRequestManager().setMessageid("-1");
                log.writeLog(message);
                return Action.FAILURE_AND_CONTINUE;
            }

        } catch (Exception e) {
//            log.debug("=========执行异常: 租赁合同终止到SAP Action {} => {}", DateUtils.datetime(), e.getMessage());
            log.writeLog("=========执行异常：" + actionName + " Action " + DateUtils.datetime() + " => " + e.getMessage());
            e.printStackTrace();
            requestInfo.getRequestManager().setMessagecontent(actionName + " Action执行异常: " + e.getMessage());
            requestInfo.getRequestManager().setMessageid("-1");
            return Action.FAILURE_AND_CONTINUE;
        }
    }

    /**
     * 封装明细表数据至List
     * @param dtIndex 明细表下标，从0开始
     * @return List<Map<String, String>>
     */
    public List<Map<String, String>> getDtMapList(int dtIndex) {
        if (dtIndex < 0) {
            throw new RuntimeException("明细表下标值非法[从0开始] => " + dtIndex);
        }
        List<Map<String, String>> res = Lists.newArrayList();
        DetailTable detailTable = requestInfo.getDetailTableInfo().getDetailTable(dtIndex);
        for (int i = 0; i < detailTable.getRowCount(); i++) {
            Row row = detailTable.getRow(i);
            Map<String, String> map = MapUtils.newCaseInsensitiveMap();
            for (int j = 0; j < row.getCellCount(); j++) {
                map.put(row.getCell(j).getName(), row.getCell(j).getValue());
            }
            res.add(map);
        }
        return res;
    }

    // 参数检验检查
    protected boolean checkParamAnno(BaseAction baseAction) throws IllegalAccessException {
        // 获取所有带ActionParamCheck注解的属性
        Class<?> clazz = baseAction.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            ActionParamCheck actionParamCheck = field.getAnnotation(ActionParamCheck.class);
            if (Objects.nonNull(actionParamCheck)) { // 有注解才check
                field.setAccessible(true); // 设置属性可访问
                String fieldVal = StringUtils.val(field.get(baseAction));
                if (StringUtils.isEmpty(fieldVal)) {
                    if (actionParamCheck.check()) { // 检查
                        isOk = false;
                        message = "参数检查错误【" + field.getName() + "】： " + actionParamCheck.errorMsg();
                        return false;
                    } else {
                        field.set(baseAction, actionParamCheck.defaultVal());
                    }
                }
            }
        }
        return true;
    }
}
